import { AmmoLib } from '../AmmoLib.js'
import { WuLiGangTi } from './WuLiGangTi.js'

function xiangLiangJiaJiao(a, b) {

	function lengthSq(v) {
		return v.x() ** 2 + v.y() ** 2 + v.z() ** 2;
	}

	const denominator = Math.sqrt( lengthSq(a) * lengthSq(b) );

	if ( denominator === 0 ) return Math.PI / 2;

	const theta = a.dot( b ) / denominator;

	return Math.acos( Math.max( -1, Math.min( 1, theta ) ) );
}

class WuLiJueSe extends WuLiGangTi {
	wuTiLeiXing = '角色'
	chiCun = null // 胶囊半径 用于判断是否站立在物体上
	zhanLiWuTi = null // 角色站立的物体
	zhanLiFaXian = null // 站立面法线
	
	constructor(canShu, shiJie) {
		super(canShu, shiJie)
		
		this.chiCun = canShu.pengZhuangTi.chiCun
		
		this.wuTi.setAngularFactor(0)
	}
	
	// 接触检测
	jieChuJianCe(AHuoB, jieChuDian, jieChuWuTi) {
		// const pengZhuangLi = jieChuDian.getAppliedImpulse() // 获取碰撞冲量
		// const weiZhi = jieChuDian['get_m_positionWorldOn' + AHuoB]()
		const benDiWeiZhi = jieChuDian['get_m_localPoint' + AHuoB]()
		// 是否在地面
		let y = benDiWeiZhi.y() // 碰撞点本地坐标y
		let { length } = this.chiCun
		let xiaXian = -length / 2 // 下限，胶囊下半圆的位置
		
		if (y < xiaXian) {
			this.zhanLiWuTi = jieChuWuTi

			const faXian = jieChuDian.get_m_normalWorldOnB()
			if (AHuoB === 'B') {
				faXian.setX(-faXian.x())
				faXian.setY(-faXian.y())
				faXian.setZ(-faXian.z())

			}
			if (this.zhanLiFaXian) AmmoLib.destroy(this.zhanLiFaXian)
			this.zhanLiFaXian = faXian
		} else {
			this.zhanLiWuTi = null
			this.zhanLiFaXian = null
		}
	}
	
	sheZhiWuTi(canShu) {
		super.sheZhiWuTi(canShu)
		
		if (!canShu.sheZhiJueSe || !this.zhanLiWuTi) return
		
		let { zou, tiao } = canShu

		const suDu = new AmmoLib.btVector3(0, 0, 0) // 默认不是0, 0, 0
		const zouVec3 = new AmmoLib.btVector3()
		const tiaoVec3 = new AmmoLib.btVector3()

		zouVec3.setValue(...zou)
		tiaoVec3.setValue(...tiao)
		// 当站立物体质量大于角色质量，角色的移速 = 相对速度 + 站立物体速度
		if (this.zhanLiWuTi.zhiLiang > this.zhiLiang) {
			let zhanLiWuTiSuDu = this.zhanLiWuTi.wuTi.getLinearVelocity()
			suDu.op_add(zhanLiWuTiSuDu)
		}
		// 大坡度禁止行走，90度为平地
		let jiaJiao = xiangLiangJiaJiao(this.zhanLiFaXian, zouVec3)
		if (jiaJiao < Math.PI * 0.8) suDu.op_add(zouVec3)
		
		suDu.op_add(tiaoVec3)
		
		this.wuTi.setLinearVelocity(suDu)

		AmmoLib.destroy(suDu)
		AmmoLib.destroy(zouVec3)
		AmmoLib.destroy(tiaoVec3)
	}
	
	gengXinWuTi() {
		const motionState = this.wuTi.getMotionState()
		const transform = new AmmoLib.btTransform()
		motionState.getWorldTransform(transform)
		const position = transform.getOrigin()
		const quaternion = transform.getRotation()
		let jieGuo = {
			bianHao: this.bianHao,
			mingZi: this.mingZi,
			zaiDiMian: Boolean(this.zhanLiWuTi),
			weiZhi: [position.x(), position.y(), position.z()]
		}

		AmmoLib.destroy(transform)
		return jieGuo
	}
}

export {
	WuLiJueSe
}